package com.skt.domain.DTO;

import lombok.Data;
import java.io.Serializable;
import java.util.Date;

/**
 * 令牌对数据传输对象 - 修复版本
 * 明确区分访问令牌和刷新令牌的过期时间
 */
@Data
public class TokenPairDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    // ========== 令牌信息 ==========
    /**
     * 访问令牌（短期有效，用于API访问，通常30分钟）
     */
    private String accessToken;

    /**
     * 刷新令牌（长期有效，用于获取新的访问令牌，通常7天）
     */
    private String refreshToken;

    // ========== 过期时间信息 ==========
    /**
     * 访问令牌过期时间（时间戳，毫秒）- 主要给前端使用
     * 前端根据这个时间来判断何时需要刷新访问令牌
     */
    private Long accessTokenExpiresIn;

    /**
     * 刷新令牌过期时间（时间戳，毫秒）- 主要用于审计和监控
     * 前端通常不需要关心这个时间，由后端自动处理刷新逻辑
     */
    private Long refreshTokenExpiresIn;

    /**
     * 令牌类型（固定为Bearer）
     */
    private String tokenType = "Bearer";

    // ========== 向后兼容字段 ==========
    /**
     * @deprecated 使用 {@link #getAccessTokenExpiresIn()} 代替
     * 保持向后兼容，新代码不应使用此字段
     */
    @Deprecated
    private Long expireTime;

    // ========== 构造方法 ==========
    public TokenPairDTO() {
    }

    public TokenPairDTO(String accessToken, String refreshToken,
                        Long accessTokenExpiresIn, Long refreshTokenExpiresIn) {
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
        this.accessTokenExpiresIn = accessTokenExpiresIn;
        this.refreshTokenExpiresIn = refreshTokenExpiresIn;
        this.expireTime = accessTokenExpiresIn; // 保持兼容
    }

    // ========== 业务方法 ==========
    /**
     * 检查令牌对是否有效
     */
    public boolean isValid() {
        return accessToken != null && !accessToken.trim().isEmpty()
                && refreshToken != null && !refreshToken.trim().isEmpty()
                && accessTokenExpiresIn != null && accessTokenExpiresIn > System.currentTimeMillis()
                && refreshTokenExpiresIn != null && refreshTokenExpiresIn > System.currentTimeMillis();
    }

    /**
     * 检查访问令牌是否即将过期（提前5分钟预警）
     */
    public boolean isAccessTokenAboutToExpire() {
        if (accessTokenExpiresIn == null) return true;
        long remaining = accessTokenExpiresIn - System.currentTimeMillis();
        return remaining < 5 * 60 * 1000; // 5分钟预警
    }

    /**
     * 检查刷新令牌是否即将过期（提前1天预警）
     */
    public boolean isRefreshTokenAboutToExpire() {
        if (refreshTokenExpiresIn == null) return true;
        long remaining = refreshTokenExpiresIn - System.currentTimeMillis();
        return remaining < 24 * 60 * 60 * 1000; // 1天预警
    }

    /**
     * 获取访问令牌剩余秒数（用于前端倒计时）
     */
    public Long getAccessTokenExpiresInSeconds() {
        if (accessTokenExpiresIn == null) return 0L;
        long remaining = (accessTokenExpiresIn - System.currentTimeMillis()) / 1000;
        return Math.max(0, remaining);
    }

    /**
     * 获取刷新令牌剩余天数（用于监控）
     */
    public Long getRefreshTokenExpiresInDays() {
        if (refreshTokenExpiresIn == null) return 0L;
        long remaining = (refreshTokenExpiresIn - System.currentTimeMillis()) / (1000 * 60 * 60 * 24);
        return Math.max(0, remaining);
    }

    /**
     * 获取访问令牌过期时间（Date对象）
     */
    public Date getAccessTokenExpiration() {
        return accessTokenExpiresIn != null ? new Date(accessTokenExpiresIn) : null;
    }

    /**
     * 获取刷新令牌过期时间（Date对象）
     */
    public Date getRefreshTokenExpiration() {
        return refreshTokenExpiresIn != null ? new Date(refreshTokenExpiresIn) : null;
    }

    // ========== 向后兼容方法 ==========
    /**
     * @deprecated 使用 {@link #getAccessTokenExpiresIn()} 代替
     */
    @Deprecated
    public Long getExpireTime() {
        return accessTokenExpiresIn != null ? accessTokenExpiresIn : expireTime;
    }

    /**
     * @deprecated 使用 {@link #setAccessTokenExpiresIn(Long)} 代替
     */
    @Deprecated
    public void setExpireTime(Long expireTime) {
        this.expireTime = expireTime;
        // 同时设置accessTokenExpiresIn保持一致性
        if (this.accessTokenExpiresIn == null) {
            this.accessTokenExpiresIn = expireTime;
        }
    }

    /**
     * 生成简化的日志信息（避免日志中暴露完整令牌）
     */
    public String toLogString() {
        return String.format(
                "TokenPair{accessToken='%s...', refreshToken='%s...', accessExpires=%s, refreshExpires=%s}",
                accessToken != null && accessToken.length() > 10 ? accessToken.substring(0, 10) : "null",
                refreshToken != null && refreshToken.length() > 10 ? refreshToken.substring(0, 10) : "null",
                accessTokenExpiresIn != null ? new Date(accessTokenExpiresIn) : "null",
                refreshTokenExpiresIn != null ? new Date(refreshTokenExpiresIn) : "null"
        );
    }
}